package com.welisit.test.service.impl;

import com.welisit.test.model.AepTimerQuartzConfig;
import com.welisit.test.service.TimerManagerService;
import org.apache.log4j.Logger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.scheduling.quartz.CronTriggerBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author welisit
 * @create 2022-04-22 16:40
 */
public class TimerManagerServiceImpl implements TimerManagerService {

    private Logger log = Logger.getLogger(TimerManagerServiceImpl.class);

    public static void main(String[] args) {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader("config/cron.txt"));
            String s = reader.readLine();
            System.out.println(s);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 查询数据库任务设置,返回列表
     *
     * @return 数据库任务设置列表
     */
    public List<AepTimerQuartzConfig> getQuartzConfig() {
        String cron = "";
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader("config/cron.txt"));
            cron = reader.readLine();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        List<AepTimerQuartzConfig> result = new ArrayList<AepTimerQuartzConfig>();
        for (int i = 0; i < 10; i++) {
            AepTimerQuartzConfig tbcq = new AepTimerQuartzConfig();
            tbcq.setTriggername("trigger" + i);
            tbcq.setCronexpression(cron);
            tbcq.setJobdetailname("jobDetail" + i);
            tbcq.setTargetobject("com.welisit.test.manager.TestTimer");
            tbcq.setMethodname("test" + i);
            tbcq.setConcurrent("1");
            tbcq.setState("1");
            tbcq.setReadme("");
            tbcq.setIsspringbean("9");
            result.add(tbcq);
        }
        return result;
    }

    /**
     * 修改任务
     *
     * @param tbcq
     * @param trigger
     * @throws Exception
     */
    public void change(AepTimerQuartzConfig tbcq, CronTriggerBean trigger, Scheduler scheduler) throws Exception {
        // 如果任务为可用
        if (tbcq.getState().equals("1")) {
            // 判断从DB中取得的任务时间和现在的quartz线程中的任务时间是否相等
            // 如果相等，则表示用户并没有重新设定数据库中的任务时间，这种情况不需要重新rescheduleJob
            if (!trigger.getCronExpression().equalsIgnoreCase(tbcq.getCronexpression())) {
                trigger.setCronExpression(tbcq.getCronexpression());
                scheduler.rescheduleJob(tbcq.getTriggername(), Scheduler.DEFAULT_GROUP, trigger);
                log.info("更新【" + tbcq.getTriggername() + "】计划任务");
            }
        } else {
            // 不可用
            scheduler.pauseTrigger(trigger.getName(), trigger.getGroup());    // 停止触发器
            scheduler.unscheduleJob(trigger.getName(), trigger.getGroup());    // 移除触发器
            scheduler.deleteJob(trigger.getJobName(), trigger.getJobGroup());// 删除任务
            log.info("删除【" + tbcq.getTriggername() + "】计划任务");
        }
    }

    /**
     * 创建/添加计划任务
     *
     * @param tbcq 计划任务配置对象
     * @throws Exception
     */
    public void createCronTriggerBean(AepTimerQuartzConfig tbcq, Scheduler scheduler, BeanFactory beanFactory) throws Exception {
        // 新建一个基于Spring的管理Job类
        MethodInvokingJobDetailFactoryBean mjdfb = new MethodInvokingJobDetailFactoryBean();
        mjdfb.setName(tbcq.getJobdetailname());// 设置Job名称
        // 如果定义的任务类为Spring的定义的Bean则调用 getBean方法
        if (tbcq.getIsspringbean().equals("1")) {
            mjdfb.setTargetObject(beanFactory.getBean(tbcq.getTargetobject()));// 设置任务类
        } else {
            // 否则直接new对象
            mjdfb.setTargetObject(Class.forName(tbcq.getTargetobject()).newInstance());// 设置任务类
        }
        mjdfb.setTargetMethod(tbcq.getMethodname());// 设置任务方法
        mjdfb.setConcurrent(tbcq.getConcurrent().equals("0") ? false : true); // 设置是否并发启动任务
        mjdfb.afterPropertiesSet();// 将管理Job类提交到计划管理类
        // 将Spring的管理Job类转为Quartz管理Job类
        JobDetail jobDetail = new JobDetail();
        jobDetail = (JobDetail) mjdfb.getObject();
        jobDetail.setName(tbcq.getJobdetailname());
        scheduler.addJob(jobDetail, true); // 将Job添加到管理类
        // 新一个基于Spring的时间类
        CronTriggerBean c = new CronTriggerBean();
        c.setCronExpression(tbcq.getCronexpression());// 设置时间表达式
        c.setName(tbcq.getTriggername());// 设置名称
        c.setJobDetail(jobDetail);// 注入Job
        c.setJobName(tbcq.getJobdetailname());// 设置Job名称
        // 通过修改misfire值来解决更新任务后立即执行的问题
//		c.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING);
        scheduler.scheduleJob(c);// 注入到管理类
        scheduler.rescheduleJob(tbcq.getTriggername(), Scheduler.DEFAULT_GROUP, c);// 刷新管理类
        log.info("新建【" + tbcq.getTriggername() + "】计划任务");
    }

}
